#include <iostream>
#include <vector>
#include <math.h>

template <typename Type_>
class Matrix {
public:
	int rows_;
	int cols_;
	std::vector<Type_> data_;

	// 构造函数接受const数组作为参数来初始化矩阵
	Matrix(int rows, int cols) : rows_(rows), cols_(cols), data_(rows*cols) {}

	void setValue(Type_* data) {
		if (data != nullptr) {
			data_.assign(data, data + rows_*cols_);
		}
	}

	void setValue(const Type_* data) {
		if (data != nullptr) {
			data_.assign(data, data + rows_*cols_);
		}
	}

	// 获取矩阵行数
	int rows() const {
		return rows_;
	}

	// 获取矩阵列数
	int cols() const {
		return cols_;
	}

	// 获取矩阵元素
	Type_& operator()(int row, int col) {
		return data_[row * cols_ + col];
	}

	// 获取矩阵元素（const版本）
	const Type_& operator()(int row, int col) const {
		return data_[row * cols_ + col];
	}

	// 矩阵转置
	Matrix<Type_> transpose() const {
		Matrix<Type_> result(cols_, rows_);
		for (int i = 0; i < rows_; i++) {
			for (int j = 0; j < cols_; j++) {
				result(j, i) = (*this)(i, j);
			}
		}
		return result;
	}

	// 矩阵相加
	Matrix<Type_> operator+(const Matrix<Type_>& other) const {
		Matrix<Type_> result(rows_, cols_);
		for (int i = 0; i < rows_; i++) {
			for (int j = 0; j < cols_; j++) {
				result(i, j) = (*this)(i, j) + other(i, j);
			}
		}
		return result;
	}

	// 矩阵相减
	Matrix<Type_> operator-(const Matrix<Type_>& other) const {
		Matrix<Type_> result(rows_, cols_);
		for (int i = 0; i < rows_; i++) {
			for (int j = 0; j < cols_; j++) {
				result(i, j) = (*this)(i, j) - other(i, j);
			}
		}
		return result;
	}

	// 矩阵乘以标量
	Matrix<Type_> operator*(Type_ scalar) const {
		Matrix<Type_> result(rows_, cols_);
		for (int i = 0; i < rows_; i++) {
			for (int j = 0; j < cols_; j++) {
				result(i, j) = (*this)(i, j) * scalar;
			}
		}
		return result;
	}

	// 矩阵除以标量
	Matrix<Type_> operator/(Type_ scalar) const {
		Matrix<Type_> result(rows_, cols_);
		for (int i = 0; i < rows_; i++) {
			for (int j = 0; j < cols_; j++) {
				result(i, j) = (*this)(i, j) / scalar;
			}
		}
		return result;
	}

	Matrix<Type_> operator*(const Matrix<Type_>& other) const {
		int resultRows = rows_;
		int resultCols = other.cols();
		Matrix<Type_> result(resultRows, resultCols);
		
		if (cols_ != other.rows()) {
			return result;
		}

		for (int i = 0; i < resultRows; i++) {
			for (int j = 0; j < resultCols; j++) {
				Type_ sum = 0.0;
				for (int k = 0; k < cols_; k++) {
					sum += data_[i*cols_+k] * other(k, j);
				}
				result(i, j) = sum;
			}
		}

		return result;
	}

	void setZeroMatrix() {
		memset(&data_[0], 0, data_.size() * sizeof(Type_));
	}

	void setRandMatrix() {
		for (int i = 0; i < rows_; i++) {
			for (int j = 0; j < cols_; j++) {
				data_[i*cols_+j] = randomFloat(0.0, 1.0);
			}
		}
	}

	Matrix<Type_>& operator=(const Matrix<Type_>& other) {
        if (this != &other) {
            rows_ = other.rows_;
			cols_ = other.cols_;
			data_ = other.data_;
        }
        return *this;
    }

	Type_ randomFloat(Type_ minVal, Type_ maxVal) {
		Type_ randomValue = (Type_)random(0, 100) / 100.0;
		return minVal + randomValue * (maxVal - minVal);
	}

	Matrix<Type_> tanhMatrix() {
		Matrix<Type_> t(rows_, cols_);
		for (int i = 0; i < rows_; i++) {
			for (int j = 0; j < cols_; j++) {
				t(i, j) = tanh(data_[i*cols_+j]);
			}
		}
		return t;
	}
};